#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>


#define TASK_NUM 10

typedef void(*task_t)();

task_t mytask[TASK_NUM];

void task1()
{
    printf("task1()\n");
}
void task2()
{
    printf("task2()\n");
}
void task3()
{
    printf("task3()\n");
}

void initTask()
{
    for (int i = 0; i < TASK_NUM; ++i)
        mytask[i] = NULL;
}

bool addTask(task_t s)
{
    for (int i = 0; i < TASK_NUM; ++i)
    {
        if (!mytask[i])
        {
            mytask[i] = s;
            return true;
        }
    }
    return false;
}

void excuteTask()
{
    addTask(task1);
    addTask(task2);
    addTask(task3);

    for (int i = 0; i < TASK_NUM; ++i)
    {
        if (!mytask[i]) continue;
        mytask[i]();
    }
}


int main()
{
    // 进程的非阻塞等待
    pid_t id = fork();
    if (0 == id)
    {
        int cnt = 6;
        while (cnt)
        {
            printf("I am child, pid : %d, ppid : %d, cnt : %d\n", getpid(), getppid(), cnt);
            sleep(1);
            cnt--;
        }
        exit(11);
    }
    int status = 0;

    while(1)
    {
        initTask();
        pid_t ret = waitpid(id, &status, WNOHANG);
        if (ret == 0)
        {
            excuteTask();
            usleep(200000);
//      printf("child process is running\n");
//            sleep(1);
        }
        else if (ret == -1)
        {
            perror("waitpid");
            return errno;
        }
        else
        {
            printf("child process has exited，");
            if (WIFEXITED(status))
            {
                printf("子进程运行完毕, exit_code : %d\n", WEXITSTATUS(status));
            }
            else
            {
                printf("子进程异常终止, sig_code : %d\n", status & 0x7f);
            }    
            break;
        }
    }
    
    


//    // 3. 使用wait等待多个进程
//    
//    // (1)创建多个进程
//    for (int i = 0; i < 10; ++i)
//    {
//        pid_t id = fork();
//        if (0 == id)
//        {
//            // child
//            int cnt = 3;
//            while (cnt--)
//            {
//                printf("I am child, pid : %d, ppid : %d, i : %d\n", getpid(), getppid(), i);
//                sleep(1);
//            }
//            exit(0);
//        }
//    }
//
//    for (int i = 0; i < 10; ++i)
//    {
//        pid_t wait_ret = waitpid(-1, NULL, 0);
//        if (-1 == wait_ret)
//        {
//            perror("wait");
//            return errno;
//        }
//        printf("wait success, pid : %d, i : %d\n", wait_ret, i);
//    }
//    sleep(3);


    // 1. 验证僵尸进程无法被杀死
    // 2. 使用wait等待一个任意子进程退出
    // 4. 使用wait时，子进程没有退出
    // 5. 使用wait时，没有子进程, 出错
    // 6. 使用函数waitpid, 它可以替代wait
    // 7. 参数status
    // 8. 与status相关的宏, WIFEXITED, WEXITSTATUS
//    printf("I am a process, pid : %d, ppid : %d\n", getpid(), getppid());
//    sleep(2);
//    pid_t id = fork();
//    if (0 == id)
//    {
//        int cnt = 3;
//        while (cnt--)
//        {
//            printf("I am child, pid : %d, ppid : %d, cnt : %d\n", getpid(), getppid(), cnt);
//            sleep(1);
//            // int k = 5 / 0; // 制造异常
//        }
//        exit(-1);
//    }
//    int cnt = 6;
//    while (cnt--)
//    {
//        printf("I am parent, pid : %d, ppid : %d\n", getpid(), getppid());
//        sleep(1);
//    }
//
////    pid_t wait_ret = wait(NULL);
//    int status = 0;
//    pid_t wait_ret = waitpid(id, &status, 0); 
//    // -1 表示wait_pid等待任意进程
//    if (wait_ret == -1)
//    {
//        printf("wait fail\n");
//        perror("wait");
//        return errno; 
//    }
//    // printf("wait success, ret : %d, sig_code : %d, exit_code : %d\n", wait_ret, status & 0x7f, (status >> 8)&0xff);
//    if (WIFEXITED(status))
//    {
//        printf("程序正常终止, exit_code : %d\n", WEXITSTATUS(status));
//    }
//    else
//    {
//        printf("程序异常终止\n");
//    }
//    sleep(3);

    return 0;
}
